<?php
/**
 * 权益校验以及操作服务
 */

namespace Biz\service\BrandRights;

use Biz\model\brand\Brand;
use Biz\model\brandAccount\BrandAccountInfo;
use Biz\model\brandActivity\BrandActivityBasic;
use Biz\model\brandRights\BrandRightsAll;
use Biz\model\brandRights\BrandRightsRecored;
use Biz\model\brandRights\BrandRightsSource;
use Biz\model\GoodsTestActivity\FineGoodsModel;
use Biz\pockets\constInterface\SourceRightsInterface;
use Doraemon\pockets\datebase\BaseDbModel;
use Doraemon\tools\Log;
use Exception;

class BrandEquityVerificationService implements SourceRightsInterface
{

    const CHECK_SOURCE_MSG = "该权益次数已用完或未开通";
    const CHECK_SOURCE_UNKNOWN_ERR_MSG = "权益核验异常";
    const CODE_ERROR_VERIFICATION = -2000;
    const CODE_ERROR_BRAND_ACCOUNT = -10000;
    const CODE_ERROR_BRAND = -10001;
    const CODE_ERROR_BRAND_RIGHTS = -10002;

    const CHECK_RIGHTS_STATUS_ERRORS = [
        self::CODE_ERROR_BRAND_ACCOUNT => '账户过期或不存在的品牌账户!',
        self::CODE_ERROR_BRAND => '不存在的品牌信息或品牌入驻时间无效!',
        self::CODE_ERROR_BRAND_RIGHTS => '权益不存在!',
        self::CODE_ERROR_VERIFICATION => self::CHECK_SOURCE_MSG
    ];

    /**
     * 获取品牌单个权益(判断是否-处于有效状态)
     * @param $brandId @品牌id
     * @param $rightsName @权益英文
     * @param bool $api
     * @param integer $currentUseNum @当前已使用的权益数量
     * @return bool
     * @throws Exception
     */
    public static function checkOneSourceStatus($brandId, $rightsName, bool $api = false, int $currentUseNum = 0): bool
    {
        try {
            //账户过期或不存在的品牌账户
            $accountInfo = BrandAccountInfo::getOneByWhere([
                'type' => BrandAccountInfo::ACCOUNT_TYPE_BRAND,
                'brand_id' => $brandId,
                'account_status' => BrandAccountInfo::ACCOUNT_STATUS_USED
            ], ['id', 'in_start_time', 'in_end_time'],
            );
            if ($accountInfo['in_end_time'] < date('Y-m-d')) {
                throw new Exception(
                    self::CHECK_RIGHTS_STATUS_ERRORS[self::CODE_ERROR_BRAND_ACCOUNT],
                    self::CODE_ERROR_BRAND_ACCOUNT
                );
            }
            //不存在的品牌信息或品牌入驻时间无效
            $brandInfo = Brand::getInfo($brandId);
            if (!$brandInfo) {
                throw new Exception(
                    self::CHECK_RIGHTS_STATUS_ERRORS[self::CODE_ERROR_BRAND],
                    self::CODE_ERROR_BRAND
                );
            }

            //$rightsType  自行查询
            $rightsInfo = BrandRightsSource::getInfo(['rights_name' => $rightsName],
                ['id', 'rights_type', 'rights_title']);
            if (!$rightsInfo) {
                throw new Exception(
                    self::CHECK_RIGHTS_STATUS_ERRORS[self::CODE_ERROR_BRAND_RIGHTS],
                    self::CODE_ERROR_BRAND_RIGHTS
                );
            }
            $rightsType = $rightsInfo['rights_type'];
            $where['rights_status'] = BaseDbModel::STATUS_NORMAL;
            $where['brand_id'] = $brandId;
            $where['end_time[>=]'] = time();
            $where['rights_name'] = $rightsName;
            //获取当前权益
            $status = false;
            switch ($rightsType) {
                //开关型（是否有该权益）其他
                case BrandRightsSource::RIGHTS_TYPE_OTHER:
                case BrandRightsSource::RIGHTS_TYPE_OPEN:
                    $status = self::getTypeOpenStatus($where);
                    break;
                //基础数量型
                case BrandRightsSource::RIGHTS_TYPE_NUM:
                    $status = self::getTypeBaseNumStatus($where, $currentUseNum);
                    break;
                //消耗型
                case BrandRightsSource::RIGHTS_TYPE_LIMIT_NUM:
                    $status = self::getTypeNumStatus($where);
                    break;
            }

            if (!$status) {
                throw new Exception($rightsInfo['rights_title'] . ':' . self::CHECK_SOURCE_MSG,
                    self::CODE_ERROR_VERIFICATION);
            }
            return true;
        } catch (Exception $e) {
            Log::error($e->getMessage(), func_get_args());
            if ($api) {
                return false;
            }
            if (in_array($e->getCode(), array_keys(self::CHECK_RIGHTS_STATUS_ERRORS))) {
                throw new Exception($e->getMessage(), self::CODE_ERROR_VERIFICATION);
            }
            throw new Exception(self::CHECK_SOURCE_UNKNOWN_ERR_MSG, self::CODE_ERROR_VERIFICATION);
        }

    }

    /**
     * 获取开关型权益状态
     * @param $where
     * @return bool
     */
    private static function getTypeOpenStatus($where): bool
    {
        $source = BrandRightsAll::getInfo($where);
        if ($source) {
            return true;
        }
        return false;
    }

    /**
     * 获取数量型权益状态
     * @param $where
     * @return bool
     */
    private static function getTypeNumStatus($where): bool
    {
        $rightsNum = BrandRightsAll::getInfo($where, 'rights_num');
        $mixNum = BrandRightsAllService::getMixPackNum($where['brand_id']);
        if (isset($where['rights_name']) && in_array($where['rights_name'], SourceRightsInterface::SPECIAL_ACTIVITY)) {
            $rightsNum = $rightsNum + $mixNum;
        }
        if ($rightsNum > 0) {
            return true;
        }
        return false;
    }

    /**
     * 获取基础数量型权益状态
     * @param $where
     * @param $num
     * @return bool
     */
    private static function getTypeBaseNumStatus($where, $num): bool
    {
        $rightsNum = BrandRightsAll::getInfo($where, 'total_num');
        if ($rightsNum && $rightsNum > $num) {
            return true;
        }
        return false;
    }

    /**
     * 品牌活动消费操作数量
     * @param int $brandId 品牌id
     * @param string $rightsName 权益英文名
     * @param int $recordType 记录类型 0:默认1:品牌套餐2:购买权益3:消费4:退返5:运营管理员
     * @param int $operateUserType
     * @param mixed $sourceId
     * @param int $type 1:加 2:减
     * @param int $adminId
     * @param int $opNum 操作数量 默认1
     * @param string $desc
     * @return array|bool
     */
    public static function addOrSubBrandSourceNum(
        int    $brandId,
        string $rightsName,
        int    $recordType,
        int    $operateUserType,
               $sourceId = 0,
        int    $type = BrandRightsRecoredService::SUB,
        int    $opNum = 1,
        int    $adminId = 0,
        string $desc = ''
    )
    {
        try {

            $rightsId = BrandRightsSourceService::getIdByRightsName($rightsName);
            if (!$rightsId) {
                Log::error('查询权益不存在！:', [$rightsName]);
                return false;
            }
            //查询当前权益
            $where['brand_id'] = $brandId;
            $where['rights_source_id'] = $rightsId;
            $sourceBrandInfo = BrandRightsAll::getInfo($where);
            if (!$sourceBrandInfo) {
                Log::error('查询当前权益不存在！:', [$where]);
                return false;
            }

            return BrandRightsAll::action(function () use (
                $brandId,
                $rightsName,
                $rightsId,
                $recordType,
                $operateUserType,
                $sourceId,
                $type,
                $adminId,
                $opNum,
                $sourceBrandInfo,
                $desc
            ) {
                $num = $sourceBrandInfo['rights_num'] ?? 0;
                $totalNum = $sourceBrandInfo['total_num'] ?? 0;
                $rightsNum = $num;
                //log日志
                $log['brand_id'] = $brandId;
                $log['rights_name'] = $rightsName;
                $log['res'] = $num;
                $log['rights_id'] = $rightsId;
                //计算消耗数据
                if ($type == BrandRightsRecoredService::SUB) {
                    if ($num <= 0 || $opNum > $num) {
                        Log::error('消费权益-数量异常:', $log);
                        return false;
                    }
                    $rightsNum = $num - $opNum;
                }
                //计算增加数据
                if ($type == BrandRightsRecoredService::ADD) {
                    if ($recordType != BrandRightsRecored::RECORED_TYPE_REFUND) {
                        $totalNum += $opNum;
                    }
                    $rightsNum = $num + $opNum;
                }
                //更新BrandRightsAll数据
                $upRes = BrandRightsAllService::updateRightsAll($rightsNum, $totalNum, $brandId, $rightsId);
                if (!$upRes) {
                    Log::debug('消费权益-更新异常:', $log);
                    return false;
                }
                $operateData = json_encode([
                    'rights_num' => $rightsNum,
                    'total_num' => $totalNum,
                    'admin_id' => $adminId,
                    'desc' => $desc
                ]);
                $insertData = [
                    $brandId,
                    $rightsName,
                    $rightsId,
                    $recordType,
                    $sourceId,
                    $sourceBrandInfo,
                    $operateData,
                    $operateUserType,
                    $adminId
                ];
                //插入BrandRightsRecord数据
                $inRes = BrandRightsRecoredService::insertRecord(...$insertData);
                if (!$inRes) {
                    Log::debug('消费权益-插入异常:', $log);
                    return false;
                }
                return true;
            });
        } catch (\Exception $e) {
            Log::error("消费权益错误", [$e->getMessage()]);
            return false;
        }
    }

    /**
     * 新品速递 好物轻测套餐减数量
     * @param $brandId
     * @param $sourceId
     * @param $rightName
     * @return bool
     */
    public static function subNum($brandId, $sourceId, $rightName): bool
    {
        $mixNum = BrandRightsAllService::getMixPackNum($brandId);
        if ($rightName == SourceRightsInterface::GOODS_TEST_A || $rightName == SourceRightsInterface::NEW_PRODUCT) {
            if ($mixNum > 0) {
                $rightName = SourceRightsInterface::NEW_PRODUCT_GOODS_TEST_A;
            }
        }
        //权益数量操作
        $dataParams = [
            $brandId,
            $rightName,
            BrandRightsRecored::RECORED_TYPE_CONSUME,
            BrandRightsRecored::OPERATE_USER_TYPE_SYS,
            $sourceId,
        ];
        return self::addOrSubBrandSourceNum(...$dataParams);
    }

    /**
     * 增加活动次数（运营）
     * @param int $brandId
     * @param string $rightsId
     * @param int $adminId
     * @param int $num
     * @param string $desc
     * @param int $levelRightsNum
     * @return bool
     * @throws Exception
     */
    public static function addRightsNumForOp(
        int    $brandId,
        string $rightsId,
        int    $adminId = 0,
        int    $num = 1,
        string $desc = '',
        int $levelRightsNum = 0
    ): bool
    {
        if (!$brandId || !$rightsId) {
            throw new \Exception('非法参数');
        }

        $accountInfo = BrandAccountInfo::getOneByWhere([
            'type' => BrandAccountInfo::ACCOUNT_TYPE_BRAND,
            'brand_id' => $brandId,
            'account_status' => BrandAccountInfo::ACCOUNT_STATUS_USED
        ], ['id', 'in_start_time', 'in_end_time']
        );
        if ($accountInfo['in_end_time'] < date('Y-m-d')) {
            throw new \Exception('账户过期或不存在的品牌账户!');
        }

        $brandInfo = Brand::getInfo($brandId);
        if (!$brandInfo) {
            Log::debug('不存在的品牌信息或品牌入驻时间无效', ['brand_id' => $brandId, 'rights_id' => $rightsId]);
            throw new \Exception('不存在的品牌信息或品牌入驻时间无效');
        }

        //查询当前权益数量
        $getWhere['brand_id'] = $brandId;
        $getWhere['rights_source_id'] = $rightsId;
        //1.查询当前权益是否存在
        $sourceBrandInfo = BrandRightsAll::getInfo($getWhere);

        $rightsType = BrandRightsSourceService::getRightsTypeById($rightsId);

        $startTime = strtotime($accountInfo['in_start_time']);
        $endTime = strtotime($accountInfo['in_end_time']);
        $endTime = strtotime(date('Y-m-d 23:59:59', $endTime));

        //2.存在更新
        if ($sourceBrandInfo) {
            if ($rightsType == BrandRightsSource::RIGHTS_TYPE_NUM) {
                $rightsNum = $totalNum = $num;
            } else {
                $rightsNum = $sourceBrandInfo['rights_num'] + $num;
                $totalNum = $sourceBrandInfo['total_num'] + $num;
            }
            $dataExt['rights_status'] = BaseDbModel::STATUS_NORMAL;
            $dataExt['start_time'] = $startTime;
            $dataExt['end_time'] = $endTime;
            $upRes = BrandRightsAllService::updateRightsAll($rightsNum, $totalNum, $brandId, $rightsId, $dataExt);
            if (!$upRes) {
                throw new \Exception('更新失败！请重试');
            }
        } else {
            //3.不存在查询套餐
            $rightsNum = $num;
            $totalNum = $rightsNum;
            $rightsName = BrandRightsSourceService::getNameById($rightsId);
            //4.增加品牌权益
            BrandRightsAllService::insertSource($brandId, $rightsId, $rightsName, $rightsNum, $startTime, $endTime);
        }
        $rightsName = BrandRightsSourceService::getNameById($rightsId);
        //5.增加记录
        $operateData = json_encode([
            'rights_num' => $rightsNum,
            'total_num' => $totalNum,
            'admin_id' => $adminId,
            'desc' => $desc,
            'op_level' => $brandInfo['level'],  //操作时对应的等级和权益数量
            'op_level_rights_num' => $levelRightsNum,
        ]);


        $insertData = [
            $brandId,
            $rightsName,
            $rightsId,
            BrandRightsRecored::RECORED_TYPE_ADMIN,
            0,
            $sourceBrandInfo,
            $operateData,
            BrandRightsRecored::OPERATE_USER_TYPE_ADMIN,
            $adminId
        ];


        BrandRightsRecoredService::insertRecord(...$insertData);
        return true;
    }

    /**
     * （活动）审核不通过退还
     * @param $brandId
     * @param $activityId
     * @param $activityType
     * @param $adminId
     * @param $params
     * @return array|bool
     */
    public static function activityRightsRefund($brandId, $activityId, $activityType, $adminId, $params = [])
    {
        $sourceId = BrandActivityBasic::getSourceId($activityType, $activityId);

        $rightName = null;

        $activictyRights = [];

        if ($activityType == BrandActivityBasic::ACTIVITY_TYPE_BLIND_BOX) {
            $rightName = SourceRightsInterface::BLIND_BOX;
        } elseif ($activityType == BrandActivityBasic::ACTIVITY_TYPE_NEW_PRODUCT) {
            $activictyRights = [
                SourceRightsInterface::NEW_PRODUCT,
                SourceRightsInterface::NEW_PRODUCT_GOODS_TEST_A,
            ];
        } elseif ($activityType == BrandActivityBasic::ACTIVITY_TYPE_LIGHT_TEST) {
            $package = $params['package'] ?? 0;
            if (isset(SourceRightsInterface::GOODS_TEST[$package])) {
                if ($package == FineGoodsModel::PACKAGE_A) {
                    $activictyRights = [
                        SourceRightsInterface::GOODS_TEST_A,
                        SourceRightsInterface::NEW_PRODUCT_GOODS_TEST_A,
                    ];
                } else {
                    $rightName = SourceRightsInterface::GOODS_TEST[$package];
                }
            }
        }

        if (!empty($activictyRights)) {
            $recoredList = BrandRightsRecored::selectList([
                    'brand_id' => $brandId,
                    'rights_name' => $activictyRights,
                    'recored_type' => BrandRightsRecored::RECORED_TYPE_CONSUME,
                    'source_id' => $sourceId,
                    'ORDER' => ['id' => 'DESC']
                ]
            );
            foreach ($recoredList as $row) {
                if ($rightName) {
                    break;
                }
                $rightName = $row['rights_name'];
            }

        }

        if (empty($rightName)) {
            return false;
        }

        //权益数量操作

        $dataParams = [
            $brandId,
            $rightName,
            BrandRightsRecored::RECORED_TYPE_REFUND,
            BrandRightsRecored::OPERATE_USER_TYPE_SYS,
            $sourceId,
            BrandRightsRecoredService::ADD,
        ];
        $bResult = BrandEquityVerificationService::addOrSubBrandSourceNum(...$dataParams);

        if (!$bResult) {
            Log::info('品牌活动退还权益失败', func_get_args());
        }

        return $bResult;
    }

}